home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Think Class Libraries / CProgressBar 1.2 / CProgressBar.p next >
Text File  |  1996-01-05  |  16KB  |  560 lines

  1. {****************************************************}
  2. {}
  3. {        CProgressBar.p                                                                                                                                                                                                }
  4. {}
  5. {        SUPERCLASS = CPane                                                                                                                                                                            }
  6. {}
  7. {        Copyright © 1994 Johns Hopkins University. All rights reserved.                                        }
  8. {}
  9. {        Original Author:     Martin R. Wachter        email:    mrw@welchgate.welch.jhu.edu            }
  10. {}
  11. {        Modified:            4/27/94                by:        mrw            TCL Version:    1.1.3                                                        }
  12. {        Created:            3/25/94                    by:        mrw            TCL Version:    1.1.3                                                        }
  13. {}
  14. {        Pascal Translation:    Patrick Hew                email:    phew@ucc.gu.uwa.edu.au                                }
  15. {}
  16. {        Modified:        3 Jan 1996            by:        phew            TCL Version: 1.1.2                                                            }
  17. {        Created:            4 Dec 1994            by:        phew            TCL Version: 1.1.2                                                            }
  18. {}
  19. {        CProgressBar is a subclass of CPane which emulates the Finder's progress            }
  20. {        bar when you copy files.  Use it like any other CPane subclass.                                                    }
  21. {}
  22. {        Call UpdateProgress with a percentage complete to "animate" the progress            }
  23. {        fill area.}
  24. {}
  25. {        You can specify any RGB colors that you want for the background and the fill        }
  26. {        bar areas of CProgressBar.  Call UseFinderProgressColors to use the same            }
  27. {        colors that the Finder uses, or call UseSystemTinges for the System's color        }
  28. {        tinges as set by the user in the Color CDEV.                                                                                                            }
  29. {}
  30. {        Important: If you creating a progress bar in a DLOG dialog as an overloaded            }
  31. {        item, remember to override your application's ForceClassReferences method        }
  32. {        to refer to CProgressBar. See CApplication.ForceClassReferences for details.    }
  33. {        Thanks to Robert "lobsterman" Huber for detecting this error.                                                    }
  34. {}
  35. {        Version change history:                                                                                                                                                                        }
  36. {    }
  37. {    1.0        Initial release.                                                                                                                                                                                        }
  38. {    1.1        FinderFillColor and FinderBackColor declared as separate functions.                        }
  39. {                    This allows Finder colors to be set at the initialization stage.                                            }
  40. {                    GetWindowTinges now a utility function instead of being a method.                            }
  41. {                    Removed automatic creation of a frame border. Creating a border is                    }
  42. {                    left to the programmer, being a separate object.                                                                                }
  43. {                    Drawing and UpdateProgress revamped to handle shadowing of the bar                }
  44. {                    correctly, and to reduce flickering during animation.                                                                    }
  45. { 1.2        Restructured into a single file.                                                                                                                                     }
  46. {                    Draw now checks for using color (and hence for the presence of Color                }
  47. {                    Quickdraw) before saving and restoring the foreground colour.                                        }
  48. {}
  49. {****************************************************}
  50.  
  51.  
  52. unit CProgressBar;
  53.  
  54. interface
  55.  
  56.     uses
  57.         TCL;
  58.  
  59.     { Synonyms for certain values. }
  60.  
  61.     const
  62.         kDontUseColor = FALSE;
  63.         kUseColor = TRUE;
  64.  
  65.         kHorizontal = FALSE;
  66.         kVertical = TRUE;
  67.  
  68.         KNoShadow = FALSE;
  69.         kShadow = TRUE;
  70.  
  71.     const
  72.         SHADOW_DEPTH = 2;
  73.  
  74.     type
  75.         CProgressBar = object(CPane)
  76.  
  77.                 useShadow: Boolean;
  78.                 isVertical: Boolean;
  79.                 useColor: Boolean;
  80.                 itsRGBFillColor: RGBColor;
  81.                 itsRGBBackColor: RGBColor;
  82.                 itsPercent: Integer;
  83.                 itsFillRect: Rect;
  84.  
  85.                 { Initialize a ProgressBar object. }
  86.                 procedure IProgressBar (anEnclosure: CView;
  87.                                             aSupervisor: CBureaucrat;
  88.                                             aWidth: Integer;
  89.                                             aHeight: Integer;
  90.                                             aHEncl: Integer;
  91.                                             aVEncl: Integer;
  92.                                             aHSizing: SizingOption;
  93.                                             aVSizing: SizingOption;
  94.                                             aColor: Boolean;
  95.                                             aVertical: Boolean;
  96.                                             aShadow: Boolean;
  97.                                             rgbFColor: RGBColor;
  98.                                             rgbBColor: RGBColor);
  99.  
  100.                 { Initialize a ProgressBar object using a template. }
  101.                 procedure IViewTemp (anEnclosure: CView;
  102.                                             aSupervisor: CBureaucrat;
  103.                                             viewData: Ptr);
  104.                 override;
  105.  
  106.                 { Use the same colors that the Finder 's progress bar uses. }
  107.                 procedure UseFinderProgressColors;
  108.  
  109.                 { Use the System 's Highlight and Window colors for the fill and back colors. }
  110.                 procedure UseSystemTinges;
  111.  
  112.                 { Draw the Progress bar. }
  113.                 procedure Draw (var area: Rect);
  114.                 override;
  115.  
  116.                 { Given a percentage of completion, UpdateProgress will set itsFillRect to the }
  117.                 { appropriate size. The Draw method actually draws the fill bar. }
  118.                 { Animate the bar by multiple calls to UpdateProgress with different values. }
  119.                 { Horizontal growth is from left to right, vertical growth from bottom to top. }
  120.                 procedure UpdateProgress (percent: Integer);
  121.  
  122.             end; { CProgressBar }
  123.  
  124.     { ProgressBar template. }
  125.  
  126.     type
  127.         ProgressBarTemp = record
  128.                 sPaneTemp: PaneTemp;
  129.                 color: Integer;        { The template stores a Boolean as two bytes. }
  130.                 vertical: Integer;    { Hence we have to read as an integer/short. }
  131.                 shadow: Integer;
  132.                 rgbFColor: RGBColor;    { These are just three integers. }
  133.                 rgbBColor: RGBColor;
  134.             end;
  135.         ProgressBarTempP = ^ProgressBarTemp;
  136.  
  137.     { Utility functions for getting colors. }
  138.     { These are generic enough that one may wish to use them elsewhere, }
  139.     { hence they have been unbundled from methods. }
  140.  
  141.     { Returns the RGB values for the Finder's fill color. }
  142.     function FinderFillColor: RGBColor;
  143.  
  144.     { Returns the RGB values for the Finder's back color. }
  145.     function FinderBackColor: RGBColor;
  146.  
  147.     { Returns the RGB values for the Finder's background color. }
  148.     procedure GetWindowTinges (var lightTinge: RGBColor;
  149.                                     var darkTinge: RGBColor);
  150.  
  151.  
  152. implementation
  153.  
  154.  
  155. {****************************************************}
  156. {}
  157. {        IProgressBar                                                                                                                                                                                                    }
  158. {}
  159. {        Initialize a ProgressBar object.                                                                                                                                             }
  160. {}
  161. {****************************************************}
  162.  
  163.     procedure CProgressBar.IProgressBar (anEnclosure: CView;
  164.                                     aSupervisor: CBureaucrat;
  165.                                     aWidth: Integer;
  166.                                     aHeight: Integer;
  167.                                     aHEncl: Integer;
  168.                                     aVEncl: Integer;
  169.                                     aHSizing: SizingOption;
  170.                                     aVSizing: SizingOption;
  171.                                     aColor: Boolean;
  172.                                     aVertical: Boolean;
  173.                                     aShadow: Boolean;
  174.                                     rgbFColor: RGBColor;
  175.                                     rgbBColor: RGBColor);
  176.  
  177.     begin { IProgressBar }
  178.         IPane(anEnclosure, aSupervisor, aWidth, aHeight, aHEncl, aVEncl, aHSizing, aVSizing);
  179.  
  180.         useColor := aColor & gSystem.hasColorQD;
  181.         isVertical := aVertical;
  182.         useShadow := aShadow;
  183.         itsRGBFillColor := rgbFColor;
  184.         itsRGBBackColor := rgbBColor;
  185.  
  186.         itsPercent := 0;
  187.     end; { IProgressBar }
  188.  
  189.  
  190. {****************************************************}
  191. {}
  192. {        IViewTemp                                                                                                                                                                                                            }
  193. {}
  194. {        Initialize a ProgressBar object using a template.                                                                                            }
  195. {}
  196. {****************************************************}
  197.  
  198.     procedure CProgressBar.IViewTemp (anEnclosure: CView;
  199.                                     aSupervisor: CBureaucrat;
  200.                                     viewData: Ptr);
  201.  
  202.         var
  203.             p: ProgressBarTempP;
  204.  
  205.     begin { IViewRes }
  206.         p := ProgressBarTempP(viewData);
  207.  
  208.         { Initialize superclass. }
  209.  
  210.         inherited IViewTemp(anEnclosure, aSupervisor, @p^.sPaneTemp);
  211.  
  212.         { Set instance variables from template. }
  213.  
  214.         useColor := (p^.color <> 0) & gSystem.hasColorQD;
  215.         isVertical := p^.vertical <> 0;
  216.         useShadow := p^.shadow <> 0;
  217.         itsRGBFillColor := p^.rgbFColor;
  218.         itsRGBBackColor := p^.rgbBColor;
  219.  
  220.         itsPercent := 0;
  221.     end; { IViewRes }
  222.  
  223.  
  224. {****************************************************}
  225. {}
  226. {        UseFinderProgressColors                                                                                                                                                                }
  227. {}
  228. {        Use the same colors that the Finder 's progress bar uses.                                                                    }
  229. {}
  230. {****************************************************}
  231.  
  232.     procedure CProgressBar.UseFinderProgressColors;
  233.  
  234.     begin { UseFinderProgressColors }
  235.         itsRGBFillColor := FinderFillColor;
  236.         itsRGBBackColor := FinderBackColor;
  237.     end; { UseFinderProgressColors }
  238.  
  239.  
  240. {****************************************************}
  241. {}
  242. {        UseSystemTinges                                                                                                                                                                                        }
  243. {}
  244. {        Use the System 's Highlight and Window colors for the fill and back colors.                }
  245. {}
  246. {****************************************************}
  247.  
  248.     procedure CProgressBar.UseSystemTinges;
  249.  
  250.         var
  251.             theBackColor, theFillColor: RGBColor;
  252.  
  253.     begin { UseSystemTinges }
  254.  
  255.         { Note that we can't pass itsRGBBackColor and itsRGBFillColor to GetWindowTinges by reference. }
  256.  
  257.         GetWindowTinges(theBackColor, theFillColor);
  258.         itsRGBBackColor := theBackColor;
  259.         itsRGBFillColor := theFIllColor;
  260.     end; { UseSystemTinges }
  261.  
  262.  
  263. {****************************************************}
  264. {}
  265. {        Draw                                                                                                                                                                                                                            }
  266. {}
  267. {        Draw the Progress bar.                                                                                                                                                                        }
  268. {}
  269. {****************************************************}
  270.  
  271.     procedure CProgressBar.Draw (var area: Rect);
  272.  
  273.         var
  274.             pen: PenState;
  275.             frameLR: LongRect;
  276.             frameR, theFillR, paintR: Rect;
  277.             savForeColor, nowColor, myBlackColor: RGBColor;
  278.  
  279.     begin { Draw }
  280.         GetFrame(frameLR);
  281.         LongToQDRect(frameLR, frameR);
  282.  
  283.         Prepare;
  284.         GetPenState(pen);
  285.         if useColor then begin
  286.             GetForeColor(savForeColor);
  287.         end; { if }
  288.         PenNormal;
  289.  
  290.         { Paint the background. }
  291.  
  292.         if SectRect(frameR, area, paintR) then begin
  293.             if useColor then begin
  294.                 nowColor := itsRGBBackColor;
  295.                 RGBForeColor(nowColor);
  296.             end { if }
  297.             else begin
  298.                 PenPat(white);
  299.             end; { else if }
  300.             PaintRect(paintR);
  301.         end; { if }
  302.  
  303.         { Paint the fill area. }
  304.  
  305.         theFillR := itsFillRect;
  306.         if SectRect(theFillR, area, paintR) then begin
  307.             if useColor then begin
  308.                 nowColor := itsRGBFillColor;
  309.                 RGBForeColor(nowColor);
  310.             end { if }
  311.             else begin
  312.                 PenPat(gray);
  313.             end; { if }
  314.             PaintRect(paintR);
  315.         end; { if }
  316.  
  317.         if useShadow & (itsPercent > 0) then begin
  318.  
  319.             if useColor then begin
  320.  
  321.                 { The identifier BlackColor is used by QuickDraw for something different. }
  322.  
  323.                 with myBlackColor do begin
  324.                     red := $0000;
  325.                     green := $0000;
  326.                     blue := $0000;
  327.                 end; { with }
  328.                 RGBForeColor(myBlackColor);
  329.             end { if }
  330.             else begin
  331.                 PenPat(black);
  332.             end; { else }
  333.  
  334.             { Recall that drawing is clipped to the pane of the frame. }
  335.             { itsFillRect is correctly sized in UpdateProgress. }
  336.  
  337.             PenSize(SHADOW_DEPTH, SHADOW_DEPTH);
  338.  
  339.             MoveTo(itsFillRect.left + SHADOW_DEPTH, itsFillRect.bottom);
  340.             LineTo(itsFillRect.right, itsFillRect.bottom);
  341.             LineTo(itsFillRect.right, itsFillRect.top + SHADOW_DEPTH);
  342.  
  343.         end;     { if }
  344.  
  345.         { Reset settings. }
  346.  
  347.         SetPenState(pen);
  348.         if useColor then begin
  349.             RGBForeColor(savForeColor);
  350.         end; { if }
  351.  
  352.     end; { Draw }
  353.  
  354.  
  355. {****************************************************}
  356. {}
  357. {        UpdateProgress }
  358. {}
  359. {        Given a percentage of completion, UpdateProgress will set itsFillRect to the         }
  360. {        appropriate size. The Draw method actually draws the fill bar.                                                    }
  361. {}
  362. {        Animate the bar by multiple calls to UpdateProgress with different values.            }
  363. {        Horizontal growth is from left to right, vertical growth from bottom to top.        }
  364. {}
  365. {****************************************************}
  366.  
  367.     procedure CProgressBar.UpdateProgress (percent: Integer);
  368.  
  369.         var
  370.             theFillRect, updateRect: Rect;
  371.             rectWidth, rectHeight, barFill, oldFill: Integer;
  372.  
  373.     begin { UpdateProgress }
  374.  
  375.         { Update only if there is a change. }
  376.  
  377.         if itsPercent <> percent then begin
  378.  
  379.             GetLengths(rectWidth, rectHeight);
  380.  
  381.             if not isVertical then begin
  382.  
  383.                 { We calculate barFill using integer processes to avoid numerical errors. }
  384.                 { However, multiplying rectWidth by percent may result in an overflow }
  385.                 { so we cast to LongInt first, then work back. }
  386.  
  387.                 barFill := Integer(LongInt(rectWidth) * LongInt(percent) div 100);
  388.                 oldFill := Integer(LongInt(rectWidth) * LongInt(itsPercent) div 100);
  389.  
  390.                 {  Growth from left to right. For intersection testing, work with respect to frame co-ordinates. }
  391.  
  392.                 if percent > itsPercent then begin
  393.                     SetRect(updateRect, oldFill, 0, barFill, rectHeight);
  394.                 end { if }
  395.                 else begin
  396.                     SetRect(updateRect, barFill, 0, oldFill, rectHeight);
  397.                 end; { else }
  398.  
  399.                 { If there is to be a shadow, define the bar width so that we can see it. }
  400.  
  401.                 if useShadow then begin
  402.                     SetRect(theFillRect, 0, 0, barFill, rectHeight - SHADOW_DEPTH);
  403.                 end { if }
  404.                 else begin
  405.                     SetRect(theFillRect, 0, 0, barFill, rectHeight);
  406.                 end; { else }
  407.  
  408.             end { if }
  409.             else begin
  410.  
  411.                 { We calculate barFill using integer processes to avoid numerical errors. }
  412.                 { However, multiplying rectHeight by percent may result in in an overflow }
  413.                 { so we cast to LongInt first, then work back. }
  414.  
  415.                 barFill := Integer(LongInt(rectHeight) * LongInt(percent) div 100);
  416.                 oldFill := Integer(LongInt(rectHeight) * LongInt(itsPercent) div 100);
  417.  
  418.                 { Growth from top to bottom. }
  419.  
  420.                 if percent > itsPercent then begin
  421.                     SetRect(updateRect, 0, rectHeight - barFill, rectWidth, rectHeight - oldFill);
  422.                 end { if }
  423.                 else begin
  424.                     SetRect(updateRect, 0, rectHeight - oldFill, rectWidth, rectHeight - barFill);
  425.                 end; { else }
  426.  
  427.                 { If there is to be a shadow, define the bar height so that we can see it. }
  428.  
  429.                 if useShadow then begin
  430.                     SetRect(theFillRect, 0, rectHeight - barFill, rectWidth - SHADOW_DEPTH, rectHeight);
  431.                 end { if }
  432.                 else begin
  433.                     SetRect(theFillRect, 0, rectHeight - barFill, rectWidth, rectHeight);
  434.                 end; { else }
  435.  
  436.             end; { else }
  437.  
  438.             { Remember - Never pass an instance variable as a parameter by reference, }
  439.             { unless you are absolutely sure that no memory is going to be shifted. }
  440.             { We can remove any doubt by using theFillRect as a temporary variable.    }
  441.  
  442.             itsFillRect := theFillRect;
  443.  
  444.             itsPercent := percent;
  445.  
  446.             Draw(updateRect);
  447.         end; { if }
  448.     end; { UpdateProgress }
  449.  
  450.  
  451. {****************************************************}
  452. {}
  453. {        FinderFillColor                                                                                                                                                                                                }
  454. {}
  455. {        Returns the RGB values for the Finder's fill color.                                                                                         }
  456. {}
  457. {****************************************************}
  458.  
  459.     function FinderFillColor: RGBColor;
  460.  
  461.         var
  462.             theColor: RGBColor;
  463.  
  464.     begin { FinderFillColor }
  465.         with theColor do begin
  466.             red := 17476;
  467.             green := 17476;
  468.             blue := 17476;
  469.         end; { with }
  470.         FinderFillColor := theColor;
  471.     end; { FinderFillColor }
  472.  
  473.  
  474. {****************************************************}
  475. {}
  476. {        FinderBackColor                                                                                                                                                                                            }
  477. {}
  478. {        Returns the RGB values for the Finder's back color.                                                                                     }
  479. {}
  480. {****************************************************}
  481.  
  482.     function FinderBackColor: RGBColor;
  483.  
  484.         var
  485.             theColor: RGBColor;
  486.  
  487.     begin { FinderBackColor }
  488.         with theColor do begin
  489.             red := Integer(52428);
  490.             green := Integer(52428);
  491.             blue := Integer(65535);
  492.         end; { with }
  493.         FinderBackColor := theColor;
  494.     end; { FinderBackColor }
  495.  
  496.  
  497. {****************************************************}
  498. {}
  499. {        GetWindowTinges                                                                                                                                                                                        }
  500. {}
  501. {        Returns the RGB values for the Finder's background color.                                                                }
  502. {}
  503. {****************************************************}
  504.  
  505.     procedure GetWindowTinges (var lightTinge: RGBColor;
  506.                                     var darkTinge: RGBColor);
  507.  
  508.         var
  509.             windowCTable: CTabHandle;
  510.  
  511.     begin { GetWindowTinges }
  512.         { Get the current colour lookup table. }
  513.  
  514.         windowCTable := CTabHandle(GetResource('wctb', 0));
  515.  
  516.         if windowCTable <> nil then begin
  517.  
  518.             { Note about compiler directives - ctTable is of }
  519.             { type CSpecArray, which has array indices 0..0 }
  520.             { However, if the resource is not nil, then we know }
  521.             { that we can retrieve the colors that we want by }
  522.             { accessing indices 11 and 12. }
  523.             { Is there is a way to do this more cleanly? }
  524.  
  525. {$PUSH}
  526. {$R-}
  527.             lightTinge := windowCTable^^.ctTable[11].rgb;
  528.             darkTinge := windowCTable^^.ctTable[12].rgb;
  529. {$POP}
  530.  
  531.             { Case for black and white window defs under system 7, both return black! }
  532.  
  533.             with lightTinge do begin
  534.                 if (red = $0000) & (green = $0000) & (blue = $0000) then begin
  535.                     red := $ffff;
  536.                     green := $ffff;
  537.                     blue := $ffff;
  538.                 end; { if }
  539.             end; { with }
  540.         end { if }
  541.         else begin
  542.  
  543.             { No window colour table, make black and white. }
  544.  
  545.             with lightTinge do begin
  546.                 red := $ffff;
  547.                 green := $ffff;
  548.                 blue := $ffff;
  549.             end; { with }
  550.             with darkTinge do begin
  551.                 red := $0000;
  552.                 green := $0000;
  553.                 blue := $0000;
  554.             end; { with }
  555.         end; { else }
  556.  
  557.     end; { GetWindowTinges }
  558.  
  559.  
  560. end. { CProgressBar }